home *** CD-ROM | disk | FTP | other *** search
- /*
- * pcxtoppm.c - Converts from a PC Paintbrush PCX file to a PPM file.
- *
- * Copyright (c) 1990 by Michael Davidson
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * This file is provided AS IS with no warranties of any kind. The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof. In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <streams/streams.h>
- #include "kludge.h"
- #include "pcxlib.h"
-
- #define PCX_MAGIC 0x0a // PCX magic number
- #define PCX_HDR_SIZE 128 // size of PCX header
- #define PCX_256_COLORS 0x0c // magic number for 256 colors
-
- #define MAXCOLORS 256
- #define MAXPLANES 4
- #define PCX_MAXVAL 255
-
- static void read_pcx_image( NXStream *fp,
- unsigned char *buf,
- int BytesPerLine,
- int Planes,
- int Height);
- static void pcx_planes_to_pixels(
- unsigned char *pixels,
- unsigned char *bitplanes,
- int bytesperline,
- int planes,
- int bitsperpixel);
- static void pcx_unpack_pixels(
- unsigned char *pixels,
- unsigned char *bitplanes,
- int bytesperline,
- int planes,
- int bitsperpixel );
- static int GetByte(NXStream *fp);
- static int GetWord(NXStream *fp);
-
- id pcxread(NXStream *ifp)
- {
- register int i;
- int Version;
- int Xmin, Ymin, Xmax, Ymax;
- int Width, Height;
- register int x, y;
- int Planes;
- int BitsPerPixel;
- int BytesPerLine;
- unsigned char Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
- unsigned char *pcximage;
- unsigned char *pcxplanes;
- unsigned char *pcxpixels;
- id pixels;
- char buffer[1024];
-
- // pcx_init(argc, argv);
-
- // ifp = pcx_openr(ifname);
-
- /*
- * read the PCX header
- */
- if (GetByte(ifp) != PCX_MAGIC) {
- pcx_error("Not a pcx file");
- }
-
- Version = GetByte(ifp); // get version #
-
- if (GetByte(ifp) != 1) { // check for PCX run length encoding
- pcx_error("Unknown encoding scheme in pcx file");
- }
-
- BitsPerPixel= GetByte(ifp);
- Xmin = GetWord(ifp);
- Ymin = GetWord(ifp);
- Xmax = GetWord(ifp);
- Ymax = GetWord(ifp);
-
- Width = (Xmax - Xmin) + 1;
- Height = (Ymax - Ymin) + 1;
-
- (void) GetWord(ifp); // ignore horizontal resolution
- (void) GetWord(ifp); // ignore vertical resolution
-
- /*
- * get the 16-color color map
- */
- for (i = 0; i < 16; i++) {
- Red[i] = GetByte(ifp);
- Green[i] = GetByte(ifp);
- Blue[i] = GetByte(ifp);
- }
-
- (void) GetByte(ifp); // skip reserved byte
- Planes = GetByte(ifp); // # of color planes
- BytesPerLine= GetWord(ifp); // # of bytes per line
- (void) GetWord(ifp); // ignore palette info
-
- /*
- * check that we can handle this image format
- */
- switch (BitsPerPixel)
- {
- case 1:
- if (Planes > 4)
- pcx_error("can't handle image with more than 4 planes");
- break;
-
- case 2:
- case 4:
- case 8:
- if (Planes == 1)
- break;
- default:
- sprintf(buffer, "can't handle %d bits per pixel image with %d planes",
- BitsPerPixel,Planes);
- pcx_error(buffer);
- }
-
-
- /*
- * read the pcx format image
- */
- NXSeek(ifp, (long)PCX_HDR_SIZE, 0);
- pcximage = (unsigned char *)malloc(BytesPerLine * Planes * Height);
- read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);
-
- /*
- * 256 color images have their color map at the end of the file
- * preceeded by a magic byte
- */
- if (BitsPerPixel == 8) {
- if (GetByte(ifp) != PCX_256_COLORS)
- pcx_error("bad color map signature" );
-
- for (i = 0; i < MAXCOLORS; i++) {
- Red[i] = GetByte(ifp);
- Green[i] = GetByte(ifp);
- Blue[i] = GetByte(ifp);
- }
- }
-
- pixels = pcx_allocarray(Width, Height);
- pcxpixels = (unsigned char *)malloc(Width+7);
-
- /*
- * convert the image
- */
- for (y = 0; y < Height; y++) {
- pcxplanes = pcximage + (y * BytesPerLine * Planes);
-
- if (Planes == 1) {
- pcx_unpack_pixels(pcxpixels, pcxplanes,
- BytesPerLine, Planes, BitsPerPixel);
- } else {
- pcx_planes_to_pixels(pcxpixels, pcxplanes,
- BytesPerLine, Planes, BitsPerPixel);
- }
-
- for (x = 0; x < Width; x++) {
- i = pcxpixels[x];
- PCX_ASSIGN(x, y, Red[i], Green[i], Blue[i]);
- }
- }
-
- pcx_close(ifp);
-
- return pixels;
- // pcx_writeppm(stdout, pixels, Width, Height, (pixval) 255, 0 );
- }
-
- static void read_pcx_image( NXStream *fp,
- unsigned char *buf,
- int BytesPerLine,
- int Planes,
- int Height)
- {
- int c;
- int nbytes;
- int count;
- char buffer[1024];
-
- nbytes = BytesPerLine * Planes * Height;
-
- while (nbytes > 0) {
- c = GetByte(fp);
- if ((c & 0xc0) != 0xc0) {
- *buf++ = c;
- --nbytes;
- continue;
- }
-
- count = c & 0x3f;
- c = GetByte(fp);
- if (count > nbytes) {
- sprintf(buffer, "repeat count spans end of image, count = %d, nbytes = %d",
- count, nbytes);
- pcx_error(buffer);
- }
-
- nbytes -= count;
- while (--count >= 0)
- *buf++ = c;
- }
- }
-
- /*
- * convert multi-plane format into 1 pixel per byte
- */
- static void pcx_planes_to_pixels(
- unsigned char *pixels,
- unsigned char *bitplanes,
- int bytesperline,
- int planes,
- int bitsperpixel)
- {
- int i, j;
- int npixels;
- unsigned char *p;
-
- if (planes > 4)
- pcx_error("can't handle more than 4 planes" );
- if (bitsperpixel != 1)
- pcx_error("can't handle more than 1 bit per pixel" );
-
- /*
- * clear the pixel buffer
- */
- npixels = (bytesperline * 8) / bitsperpixel;
- p = pixels;
- while (--npixels >= 0)
- *p++ = 0;
-
- /*
- * do the format conversion
- */
- for (i = 0; i < planes; i++) {
- int pixbit, bits, mask;
-
- p = pixels;
- pixbit = (1 << i);
- for (j = 0; j < bytesperline; j++) {
- bits = *bitplanes++;
- for (mask = 0x80; mask != 0; mask >>= 1, p++)
- if (bits & mask)
- *p |= pixbit;
- }
- }
- }
-
- /*
- * convert packed pixel format into 1 pixel per byte
- */
- static void pcx_unpack_pixels(
- unsigned char *pixels,
- unsigned char *bitplanes,
- int bytesperline,
- int planes,
- int bitsperpixel )
- {
- register int bits;
-
- if (planes != 1)
- pcx_error("can't handle packed pixels with more than 1 plane" );
- if (bitsperpixel == 8) {
- while (--bytesperline >= 0)
- *pixels++ = *bitplanes++;
- } else if (bitsperpixel == 4) {
- while (--bytesperline >= 0) {
- bits = *bitplanes++;
- *pixels++ = (bits >> 4) & 0x0f;
- *pixels++ = (bits ) & 0x0f;
- }
- } else if (bitsperpixel == 2) {
- while (--bytesperline >= 0) {
- bits = *bitplanes++;
- *pixels++ = (bits >> 6) & 0x03;
- *pixels++ = (bits >> 4) & 0x03;
- *pixels++ = (bits >> 2) & 0x03;
- *pixels++ = (bits ) & 0x03;
- }
- } else if (bitsperpixel == 1) {
- while (--bytesperline >= 0) {
- bits = *bitplanes++;
- *pixels++ = ((bits & 0x80) != 0);
- *pixels++ = ((bits & 0x40) != 0);
- *pixels++ = ((bits & 0x20) != 0);
- *pixels++ = ((bits & 0x10) != 0);
- *pixels++ = ((bits & 0x08) != 0);
- *pixels++ = ((bits & 0x04) != 0);
- *pixels++ = ((bits & 0x02) != 0);
- *pixels++ = ((bits & 0x01) != 0);
- }
- }
- }
-
- static int GetByte(NXStream *fp)
- {
- int c;
-
- if ((c = NXGetc(fp)) == EOF)
- pcx_error("unexpected end of file" );
-
- return c;
- }
-
- static int GetWord(NXStream *fp)
- {
- int c;
-
- c = GetByte(fp);
- c |= (GetByte(fp) << 8);
- return c;
- }
-